
#include "Table.h"
#include <iostream>

using namespace RackNetPoker;

Table::Table()
: m_maxPlayers(8),
  m_currentPlayer(0),
  m_currentDealer(0),
  m_currentTime(0),
  m_smallBlind(10)
{
}

void Table::Game()
{
	while(true)
	{

		if(!CanStart())
			return;

		// ... mescolo il mazzo
		m_deck.Shuffle();

		// ... buio e doppio buio
		// ... (potenziale) giro puntate

		GetNextPlayer()->Pay(m_smallBlind);
		m_lastMaxRaise = GetNextPlayer();
		m_lastMaxRaise->Pay(m_smallBlind * 2);
		m_lastPlayer = m_lastMaxRaise;

		m_currentMaxBid = m_smallBlind * 2;

		// ... consegno le carte ai giocatori
		size_t playersNum = m_playerStates.size();
		for(size_t i = 0; i < playersNum; ++i)
		{
			m_playerStates[i].m_cards[0] = m_deck.PopCard();
			m_playerStates[i].m_cards[1] = m_deck.PopCard();

			std::cout << m_playerStates[i].ToString() << std::endl;
		}

		NewBidTurn();

		m_deck.PopCard(); // si brucia la prima carta dal mazzo

		// scopro le prime tre carte e notificalo ai client
		m_communityCards.push_back(m_deck.PopCard());
		m_communityCards.push_back(m_deck.PopCard());
		m_communityCards.push_back(m_deck.PopCard());

		std::cout << "\n[CARTE IN TAVOLA] "
			<< m_communityCards[0].ToString() << ", "
			<< m_communityCards[1].ToString() << ", "
			<< m_communityCards[2].ToString() << std::endl << std::endl;

		m_currentPlayer = m_currentDealer;
		_ResetStates();
		NewBidTurn();

		m_deck.PopCard(); // si brucia la prima carta dal mazzo

		// scropro un'altra carta e notificalo ai client
		m_communityCards.push_back(m_deck.PopCard());

		std::cout << "\n[CARTE IN TAVOLA] "
			<< m_communityCards[0].ToString() << ", "
			<< m_communityCards[1].ToString() << ", "
			<< m_communityCards[2].ToString() << ", "
			<< m_communityCards[3].ToString() << std::endl << std::endl;

		m_currentPlayer = m_currentDealer;
		_ResetStates();
		NewBidTurn();

		m_deck.PopCard(); // si brucia la prima carta dal mazzo

		// scropro l'ultima carta carta e notificalo ai client
		m_communityCards.push_back(m_deck.PopCard());

		std::cout << "\n[CARTE IN TAVOLA] "
			<< m_communityCards[0].ToString() << ", "
			<< m_communityCards[1].ToString() << ", "
			<< m_communityCards[2].ToString() << ", "
			<< m_communityCards[3].ToString() << ", "
			<< m_communityCards[4].ToString() << std::endl << std::endl;

		m_currentPlayer = m_currentDealer;
		_ResetStates();
		NewBidTurn();

		// ... CALCOLA IL/I VINCITORI e notificalo ai client
		m_evaluator.Eval(m_communityCards, m_playerStates);
		// ... si sposta il grande buio e il dealer

	}
}

void Table::AddPlayer(Player& player)
{
	m_playerStates.push_back(player);
}

Player* Table::GetNextPlayer()
{
	if(m_currentPlayer + 1 < m_playerStates.size())
		++m_currentPlayer;
	else
		m_currentPlayer = 0;

	if(m_playerStates[m_currentPlayer].m_state != Player::PS_FOLD &&
	   m_playerStates[m_currentPlayer].m_state != Player::PS_ALLIN)
		return &m_playerStates[m_currentPlayer];

	return GetNextPlayer();
}

bool Table::CanStart() const
{
	return ( m_playerStates.size() > 1 );
}

void Table::_ResetStates()
{
	for(size_t i = 0; i < m_playerStates.size(); ++i)
	{
		if(m_playerStates[i].m_state == Player::PS_CHECK || m_playerStates[i].m_state == Player::PS_RAISE)
			m_playerStates[i].m_state = Player::PS_NONE;
	}
}

bool Table::IsTurnEnd() const
{
	for(size_t i = 0; i < m_playerStates.size(); ++i)
	{
		if(m_playerStates[i].m_state == Player::PS_NONE)
			return false;
	}

	return true;
}

void Table::NewBidTurn()
{
	/*Player* nextPlayer = GetNextPlayer();
	nextPlayer->Turn(m_lastMaxRaise->m_bid);
	m_lastMaxRaise = nextPlayer;
	while((nextPlayer = GetNextPlayer()) != m_lastMaxRaise)
	{
		nextPlayer->Turn(m_lastMaxRaise->m_bid);
		if(nextPlayer->m_state == Player::PS_RAISE)
		{
			m_lastMaxRaise = nextPlayer;
		}
	}*/

	while(!IsTurnEnd())
	{
		Player* currentPlayer = GetNextPlayer();
		currentPlayer->Turn(m_currentMaxBid);
		if(currentPlayer->m_state == Player::PS_RAISE)
		{
			m_currentMaxBid = currentPlayer->m_bid;
			_ResetStates();
			currentPlayer->m_state = Player::PS_RAISE;
		}
	}
}